home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / rcs5ap1s.lzh / RCSKEEP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-30  |  9.6 KB  |  384 lines

  1. /*
  2.  *                     RCS keyword extraction
  3.  */
  4. /*****************************************************************************
  5.  *                       main routine: getoldkeys()
  6.  *                       Testprogram: define KEEPTEST
  7.  *****************************************************************************
  8.  */
  9.  
  10. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  11.    Copyright 1990 by Paul Eggert
  12.    Distributed under license by the Free Software Foundation, Inc.
  13.  
  14. This file is part of RCS.
  15.  
  16. RCS is free software; you can redistribute it and/or modify
  17. it under the terms of the GNU General Public License as published by
  18. the Free Software Foundation; either version 1, or (at your option)
  19. any later version.
  20.  
  21. RCS is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. GNU General Public License for more details.
  25.  
  26. You should have received a copy of the GNU General Public License
  27. along with RCS; see the file COPYING.  If not, write to
  28. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  
  30. Report problems and direct all questions to:
  31.  
  32.     rcs-bugs@cs.purdue.edu
  33.  
  34. */
  35.  
  36.  
  37.  
  38. /* $Log: rcskeep.c,v $
  39.  * Revision 5.3  1991/01/30  14:21:32  apratt
  40.  * CI with RCS version 5
  41.  *
  42.  * Revision 5.2  90/10/04  06:30:20  eggert
  43.  * checked in with -k by apratt at 91.01.10.13.15.20.
  44.  * 
  45.  * Revision 5.2  1990/10/04  06:30:20  eggert
  46.  * Parse time zone offsets; future RCS versions may output them.
  47.  *
  48.  * Revision 5.1  1990/09/20  02:38:56  eggert
  49.  * ci -k now checks dates more thoroughly.
  50.  *
  51.  * Revision 5.0  1990/08/22  08:12:53  eggert
  52.  * Retrieve old log message if there is one.
  53.  * Don't require final newline.
  54.  * Remove compile-time limits; use malloc instead.  Tune.
  55.  * Permit dates past 1999/12/31.  Ansify and Posixate.
  56.  *
  57.  * Revision 4.6  89/05/01  15:12:56  narten
  58.  * changed copyright header to reflect current distribution rules
  59.  * 
  60.  * Revision 4.5  88/08/09  19:13:03  eggert
  61.  * Remove lint and speed up by making FILE *fp local, not global.
  62.  * 
  63.  * Revision 4.4  87/12/18  11:44:21  narten
  64.  * more lint cleanups (Guy Harris)
  65.  * 
  66.  * Revision 4.3  87/10/18  10:35:50  narten
  67.  * Updating version numbers. Changes relative to 1.1 actually relative
  68.  * to 4.1
  69.  * 
  70.  * Revision 1.3  87/09/24  14:00:00  narten
  71.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  72.  * warnings)
  73.  * 
  74.  * Revision 1.2  87/03/27  14:22:29  jenkins
  75.  * Port to suns
  76.  * 
  77.  * Revision 4.1  83/05/10  16:26:44  wft
  78.  * Added new markers Id and RCSfile; extraction added.
  79.  * Marker matching with trymatch().
  80.  * 
  81.  * Revision 3.2  82/12/24  12:08:26  wft
  82.  * added missing #endif.
  83.  *
  84.  * Revision 3.1  82/12/04  13:22:41  wft
  85.  * Initial revision.
  86.  *
  87.  */
  88.  
  89. /*
  90. #define KEEPTEST
  91. */
  92. /* Testprogram; prints out the keyword values found. */
  93.  
  94. #include  "rcsbase.h"
  95.  
  96. libId(keepId, "$Id: rcskeep.c,v 5.3 1991/01/30 14:21:32 apratt Exp $")
  97.  
  98. static int checknum P((const char*,int));
  99. static int getprevdate P((FILE*));
  100. static int getprevid P((int,FILE*,struct buf*));
  101. static int getprevrev P((FILE*));
  102. static int getval P((FILE*,struct buf*,int));
  103. static int get0val P((int,FILE*,struct buf*,int));
  104.  
  105. struct buf prevauthor, prevrev, prevstate;
  106. char prevdate[datesize];
  107.  
  108.     int
  109. getoldkeys(fp)
  110.     register FILE *fp;
  111. /* Function: Tries to read keyword values for author, date,
  112.  * revision number, and state out of the file fp.
  113.  * The results are placed into
  114.  * prevauthor, prevdate, prevrev, prevstate.
  115.  * Aborts immediately if it finds an error and returns false.
  116.  * If it returns true, it doesn't mean that any of the
  117.  * values were found; instead, check to see whether the corresponding arrays
  118.  * contain the empty string.
  119.  */
  120. {
  121.     register int c;
  122.     char keyword[keylength+1];
  123.     register char * tp;
  124.  
  125.     /* initialize to empty */
  126.     bufscpy(&prevauthor, "");
  127.     bufscpy(&prevrev, "");
  128.     bufscpy(&prevstate, "");
  129.     *prevdate = 0;
  130.  
  131.     while( (c=getc(fp)) != EOF) {
  132.         if ( c==KDELIM) {
  133.         do {
  134.         /* try to get keyword */
  135.         tp = keyword;
  136.         while ((c=getc(fp))!=EOF && c!='\n' && c!=KDELIM && c!=VDELIM 
  137.                && tp<keyword+keylength
  138.         )
  139.             *tp++ = c;
  140.         } while (c==KDELIM);
  141.         if (c==EOF)
  142.         break;
  143.             if (c!=VDELIM) continue;
  144.         *tp = c;
  145.         if ((c=getc(fp))!=' ' && c!='\t')
  146.         continue;
  147.  
  148.         switch (trymatch(keyword)) {
  149.             case Author:
  150.         if (!getprevid(0, fp, &prevauthor))
  151.             return false;
  152.         c = getc(fp);
  153.                 break;
  154.             case Date:
  155.         if (!(c = getprevdate(fp)))
  156.             return false;
  157.                 break;
  158.             case Header:
  159.             case Id:
  160.         if (!(
  161.               getval(fp, (struct buf*)nil, false) &&
  162.               getprevrev(fp) &&
  163.               (c = getprevdate(fp)) &&
  164.               getprevid(c, fp, &prevauthor) &&
  165.               getprevid(0, fp, &prevstate)
  166.         ))
  167.             return false;
  168.         /* Skip either ``who'' (new form) or ``Locker: who'' (old).  */
  169.         if (getval(fp, (struct buf*)nil, true) &&
  170.             getval(fp, (struct buf*)nil, true))
  171.             c = getc(fp);
  172.         else if (nerror)
  173.             return false;
  174.         else
  175.             c = KDELIM;
  176.         break;
  177.             case Locker:
  178.             case Log:
  179.             case RCSfile:
  180.             case Source:
  181.         if (!getval(fp, (struct buf*)nil, false))
  182.             return false;
  183.         c = getc(fp);
  184.                 break;
  185.             case Revision:
  186.         if (!getprevrev(fp))
  187.             return false;
  188.         c = getc(fp);
  189.                 break;
  190.             case State:
  191.         if (!getprevid(0, fp, &prevstate))
  192.             return false;
  193.         c = getc(fp);
  194.                 break;
  195.             default:
  196.                continue;
  197.             }
  198.         if (c != KDELIM) {
  199.         error("closing %c missing on keyword", KDELIM);
  200.         return false;
  201.         }
  202.         if (*prevauthor.string && *prevdate && *prevrev.string && *prevstate.string) {
  203.                 break;
  204.            }
  205.         }
  206.     }
  207.  
  208.     arewind(fp);
  209.     return true;
  210. }
  211.  
  212.  
  213.     static int
  214. getval(fp, target, optional)
  215.     register FILE *fp;
  216.     struct buf *target;
  217.     int optional;
  218. /* Reads a keyword value from FP into TARGET.
  219.  * Returns true if one is found, false otherwise.
  220.  * Does not modify target if it is nil.
  221.  * Do not report an error if OPTIONAL is set and KDELIM is found instead.
  222.  */
  223. {
  224.     return get0val(getc(fp), fp, target, optional);
  225. }
  226.  
  227.     static int
  228. get0val(c, fp, target, optional)
  229.     register int c;
  230.     register FILE *fp;
  231.     struct buf *target;
  232.     int optional;
  233. /* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly.
  234.  * Same as getval, except C is the lookahead character.
  235.  */
  236. {   register char * tp;
  237.     const char *tlim;
  238.     register int got1;
  239.  
  240.     if (target) {
  241.     bufalloc(target, 1);
  242.     tp = target->string;
  243.     tlim = tp + target->size;
  244.     } else
  245.     tlim = tp = 0;
  246.     got1 = false;
  247.     for (;;  c = getc(fp))
  248.     switch (c) {
  249.         default:
  250.         got1 = true;
  251.         if (tp) {
  252.             *tp++ = c;
  253.             if (tlim <= tp)
  254.             tp = bufenlarge(target, &tlim);
  255.         }
  256.         continue;
  257.  
  258.         case ' ':
  259.         case '\t':
  260.         if (tp) {
  261.             *tp = 0;
  262. #            ifdef KEEPTEST
  263.             VOID printf("getval: %s\n", target);
  264. #            endif
  265.         }
  266.         if (!got1)
  267.             error("too much white space in keyword value");
  268.         return got1;
  269.  
  270.         case KDELIM:
  271.         if (!got1 && optional)
  272.             return false;
  273.         /* fall into */
  274.         case '\n':
  275.         case 0:
  276.         case EOF:
  277.         error("badly terminated keyword value");
  278.         return false;
  279.     }
  280. }
  281.  
  282.  
  283.     static int
  284. getprevdate(fp)
  285. FILE *fp;
  286. /* Function: reads a date prevdate; checks format
  287.  * Return 0 on error, lookahead character otherwise.
  288.  */
  289. {
  290.     struct buf prevday, prevtime, prevzone, prev;
  291.     register const char *p;
  292.     register int c;
  293.  
  294.     c = 0;
  295.     bufautobegin(&prevday);
  296.     if (getval(fp,&prevday,false)) {
  297.     bufautobegin(&prevtime);
  298.     if (getval(fp,&prevtime,false)) {
  299.         bufautobegin(&prevzone);
  300.         bufscpy(&prevzone, "");
  301.         c = getc(fp);
  302.         if (c=='-' || c=='+')
  303.         c = get0val(c,fp,&prevzone,false) ? getc(fp) : 0;
  304.         if (c) {
  305.         bufautobegin(&prev);
  306.         p = prevday.string;
  307.         bufalloc(&prev, strlen(p) + strlen(prevtime.string) + strlen(prevzone.string) + 5);
  308.         VOID sprintf(prev.string, "%s%s %s %s", 
  309.             /* Parse dates put out by old versions of RCS.  */
  310.             isdigit(p[0]) && isdigit(p[1]) && p[2]=='/'  ?  "19"  :  "",
  311.             p, prevtime.string, prevzone.string
  312.         );
  313.         str2date(prev.string, prevdate);
  314.         bufautoend(&prev);
  315.         }
  316.         bufautoend(&prevzone);
  317.     }
  318.     bufautoend(&prevtime);
  319.     }
  320.     bufautoend(&prevday);
  321.     return c;
  322. }
  323.  
  324.     static int
  325. getprevid(c, fp, b)
  326.     int c;
  327.     FILE *fp;
  328.     struct buf *b;
  329. /* Get previous identifier from C+FP into B.  */
  330. {
  331.     if (!get0val(c?c:getc(fp), fp, b, false))
  332.         return false;
  333.     checksid(b->string);
  334.     return true;
  335. }
  336.  
  337.     static int
  338. getprevrev(fp)
  339.     FILE *fp;
  340. /* Get previous revision from FP into prevrev.  */
  341. {
  342.     return getval(fp,&prevrev,false) && checknum(prevrev.string,-1);
  343. }
  344.  
  345.  
  346.     static int
  347. checknum(sp,fields)
  348.     register const char *sp;
  349.     int fields;
  350. {    register int dotcount;
  351.      dotcount=0;
  352.      while(*sp) {
  353.         if (*sp=='.') dotcount++;
  354.     else if (!isdigit(*sp)) return false;
  355.         sp++;
  356.      }
  357.      return fields<0 ? dotcount&1 : dotcount==fields;
  358. }
  359.  
  360.  
  361.  
  362. #ifdef KEEPTEST
  363.  
  364. const char cmdid[] ="keeptest";
  365.  
  366.     int
  367. main(argc, argv)
  368. int  argc; char  *argv[];
  369. {
  370.         while (*(++argv)) {
  371.         FILE *f;
  372.         if (!(f = fopen(*argv,"r"))) {
  373.             perror(f);
  374.             exit(1);
  375.         }
  376.         getoldkeys(f);
  377.         VOID fclose(f);
  378.                 VOID printf("%s:  revision: %s, date: %s, author: %s, state: %s\n",
  379.                 *argv, prevrev.string, prevdate.string, prevauthor.string, prevstate.string);
  380.     }
  381.     exitmain(EXIT_SUCCESS);
  382. }
  383. #endif
  384.